import { ShaderMaterial, Color,DoubleSide,Vector3,
    GLSL3, Vector2, RawShaderMaterial } from "three";
/**
 * 花瓣材质装饰器  通过噪声重复来模拟花瓣纹理
 * 
 * const pbrFlowerMat = new MeshPhysicalMaterial();
 * 
 * const beforeCompile = petalStdDecorator({
    bgColor: { value: new Color(0.8, 0.8, .8) },
    noiseScale: { value: curveParams.noiseScale },
    noiseOffset: { value: curveParams.noiseOffset }
});
 * 
 * pbrFlowerMat.onBeforeCompile = beforeCompile;
 * */
export const petalStdDecorator = (flowerUniform)=>{
  return (shader)=>{
        shader.uniforms.bgColor = flowerUniform.bgColor;
        shader.uniforms.noiseScale = flowerUniform.noiseScale;
        shader.uniforms.noiseOffset = flowerUniform.noiseOffset;
        shader.vertexShader = shader.vertexShader.replace('void main() {', `
        varying vec2 vUv;
        void main() {
            vUv = uv;
      `)
    
        shader.fragmentShader = shader.fragmentShader.replace('void main() {', `
        uniform vec3 bgColor;    
        uniform float noiseScale;
        uniform float noiseOffset;
        varying vec2 vUv;
        float rand(float i){ 
            return fract(sin(i *46.34 )*7346.278 );
            }
            
            //一维
            float noise(float x){
                float i = floor(x) ;
                float f = fract(x) ;
                float d = mix(rand(i), rand(i+1.0),f);
                 d = mix(rand(i), rand(i+1.0),smoothstep(0.,1.,f));
                return d;
            }
        void main() { `)
        shader.fragmentShader = shader.fragmentShader.replace('vec4 diffuseColor = vec4( diffuse, opacity );',
        `
        float noise1 = noise((vUv.y +noiseOffset) * noiseScale);
        float a1 = mix(0.,vUv.y, vUv.x);// 我也不知道为啥这么连
        float a2 = mix(noise1,0.5, a1);
        // 最后才是颜色渐变
        // 那个只有两个节点，其实就可以把其中一端不变部分处理掉
        a2 *= smoothstep(0.1,1.,vUv.x);
        vec3 col2 = mix(bgColor,diffuse, a2);
        vec4 diffuseColor = vec4( col2, opacity );
        `)
    }
}
/**
 * 等同于自发光材质
 * @returns ()=>ShaderMaterial
 */
export const  getPetalMat =()=>  new ShaderMaterial({
    vertexShader: /*glsl*/`
    varying vec2 vUv;
    void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        vec4 viewPosition = viewMatrix * modelPosition;
        vec4 projectedPosition = projectionMatrix * viewPosition;
        gl_Position = projectedPosition;
    }   
    `,
    fragmentShader: /*glsl*/`
    uniform vec3 color;
    uniform vec3 bgColor;
    varying vec2 vUv;
    uniform float noiseScale;
    uniform float noiseOffset;
    float rand(float i){ 
        return fract(sin(i *46.34 )*7346.278 );
        }
        
        //一维
        float noise(float x){
            float i = floor(x) ;
            float f = fract(x) ;
            float d = mix(rand(i), rand(i+1.0),f);
             d = mix(rand(i), rand(i+1.0),smoothstep(0.,1.,f));
            return d;
        }
        vec3 colorRamp(float fac){
            vec3 colors[2];
            float posList[2];
            posList[0] = 0.591;
            posList[1] = 1.;
            colors[0] = vec3(0.4,0.1,0.36);
            colors[1] = vec3(1.,1.,1.);
            vec3 color = vec3(0.);
            if(fac <= 0.0 ) return colors[0];
            for (int i = 0; i < 2; i++) {
                if(fac < posList[i]){
                    float a = (posList[i] -fac)/( posList[i] - posList[i-1]);
                    float h = mix(posList[i-1], posList[i], a);
                    color = mix(colors[i-1], colors[i], a);
                    break;
                } 
            }
            return mix(colors[0], colors[1], smoothstep(posList[0], posList[1], fac));
        }

        float ramp1 (float fac){
            float val[4];
            float posList[4];
            float value = 0.0;
            posList[0] = 0.;
            posList[1] = 0.4;
            posList[2] = 0.6;
            posList[3] = 1.;
            val[0]  = 0.0;
            val[1]  = 1.0;
            val[2]  = 1.0;
            val[3]  = 0.0;
            if( fac <= 0.0 ) return val[0];
            for (int i = 0; i < 4; i++) {
                if(fac < posList[i]){
                    float a = (posList[i] -fac)/( posList[i] - posList[i-1]);
                    float h = mix(posList[i-1], posList[i], a);
                    value = mix(val[i-1], val[i], a);
                    break;
                }
            }
            return value;
        }

        float ramp2 (float fac){
            const int NUM = 2;
            float val[NUM];
            float posList[NUM];
            float value = 0.0;
            posList[0] = 0.5;
            posList[1] = 1.0;
            val[0]  = .6;
            val[1]  = 0.0;
            if( fac <= 0.0 ) return val[0];
            for (int i = 0; i < NUM; i++) {
                if(fac < posList[i]){
                    float a = (posList[i] -fac)/( posList[i] - posList[i-1]);
                    float h = mix(posList[i-1], posList[i], a);
                    value = mix(val[i-1], val[i], a);
                    break;
                }
            }
            return value;
        }
    void main() {
        float noise1 = noise((vUv.y +noiseOffset) * noiseScale);
        float a1 = mix(0., ramp1(vUv.y), vUv.x);// 我也不知道为啥这么连
        float a2 = mix(ramp2(noise1),1., a1);
        // 最后才是颜色渐变
        // 那个只有两个节点，其实就可以把其中一端不变部分处理掉
        // a2 *= smoothstep(0.4,1.5,vUv.x);
        vec3 col2 = colorRamp(a2);
        // vec3 col = mix( color,bgColor ,sin(vUv.y * 100.0 ));
        gl_FragColor = vec4(col2,1.0);
    }   
    `,
    uniforms:{
        // dd55b2
        color: { value: new Color(0.9, 0.3, 0.7) },
        bgColor: { value: new Color(0.8, 0.8, .8) },
        noiseScale: { value: 80 },
        noiseOffset: { value: 0 },
    },
    side: DoubleSide,
})

/**
 * 着色器版的弯曲，也是材质啊
 * 仅用于xyo平面 
 */
export const getBendDecorator = (uniforms={bendFactor:{value:0.5},bendRadius:{value:1}})=>{
    function bc(shader) {
        shader.uniforms.bendFactor = uniforms.bendFactor;
        shader.uniforms.bendRadius = uniforms.bendRadius;
        const paramStr = `
        uniform float bendFactor;
        uniform float bendRadius;
        #define TWO_PI 2.0 * PI
        `
        shader.vertexShader = shader.vertexShader.replace('void main() {', `${paramStr}
            void main() {`);
        const posStr = /*glsl */`
        pos *= bendRadius;  
        pos2 *= bendRadius;
            vec3 transformed  = mix(mix(position,pos, bendFactor*2.), mix(pos, pos2, (bendFactor -0.5) *2.), node1);`
        const normalStr = /*glsl */`
            float  theta = (uv.x -0.5) * TWO_PI,
                   phi = (uv.y -0.5) * PI;
                //    factor为0.5的时候成一个圆柱
            float node1 = step( 0.5, bendFactor),
                  node2 = step( 0.6, bendFactor);    
            float r2 =  cos(phi);       
            // 球
            vec3 pos = vec3(
                sin(theta) ,
                (uv.y -0.5)*2.,
                cos(theta) 
            );
            // 圆柱
            vec3 pos2 = vec3(
                sin(theta) * r2,
                sin(phi),
                cos(theta) * r2
            );
            //点即法向
            vec3 objectNormal = mix(normalize(mix(normal,pos, bendFactor *2.)),  normalize(mix(normalize(pos), pos2 , (bendFactor -0.5) *2.)), node2);
        `        
        shader.vertexShader = shader.vertexShader.replace('#include <beginnormal_vertex>', normalStr);
        // shader.vertexShader = shader.vertexShader.replace('#include <defaultnormal_vertex>', ``);
        shader.vertexShader = shader.vertexShader.replace('#include <begin_vertex>', posStr);
             


    }
     new ShaderMaterial({
        vertexShader: /*glsl*/`
        uniform float bendFactor;
        uniform float bendRadius;
        in vec2 uv;
        varying vec2 vUv;
        const float PI = 3.1415926535897932384626433832795;
        const float TWO_PI = 2.0 * PI;

        void main() {
            // 有了uv 我iju可以直接用uv弯曲了，不对，还是要考虑xyz
            vUv = uv;
            float  theta = uv.x * TWO_PI,
                   phi = (uv.y -0.5) * PI;
            vec3 pos = vec3(
                sin(theta) * cos(phi),
                sin(phi),
                cos(theta) * cos(phi)
            );     
            pos *= bendRadius;  
            vec4 modelPosition = modelMatrix * vec4(mix(pos, position, bendFactor), 1.0);
            vec4 viewPosition = viewMatrix * modelPosition;
            vec4 projectedPosition = projectionMatrix * viewPosition;   
            gl_Position = projectedPosition;
        }
        `,
        fragmentShader: /*glsl*/`
         
        `,
        uniforms:{
            noiseScale: { value: 80 },
            noiseOffset: { value: 0 },
        },
        side: DoubleSide,
    });
    return bc;
}

export function getWaveMat(uniformsObj){
    const fragment = /* glsl */ `
// #version 300 es
precision highp float;
out vec4 oColor;
#define gl_FragColor oColor
#define varying in 
#define  pi 3.14159265359 

uniform float u_Time;
uniform vec2 u_CanvasSize;
in vec3 v_Color;
in vec2 v_Uv;
in vec3 v_WorldPosition;

uniform int pointsNum ;
uniform  vec3 [10] points;
uniform  float [10] startTimes;
uniform  vec3 [10] directions;// 点击的法向

//  差值 和 宽度的一半  模糊
float line(float delta, float w,float d) {
      return smoothstep(w + d, w-d, abs(delta));
}

float circle(vec2 position, vec2 center, float radius) {
      vec2 d = position - center;
      return radius * radius - dot(d, d);
}
float circle2 ( float distSq , float radius){
      return radius - sqrt(distSq) ;
}

float easeInOut(float t){ 
//     return t*t*(3.0-2.0 * t);
    return t* t*t*(3.0-2.0 * t)* (3.0-2.0 * t);
}


void main() {
      vec2 st = v_Uv;
      float time = u_Time ;
     
// 循环 加圆
float c =0., ca = 0.,r;
vec4 color = vec4(0.4,1.,1.,0.0);
vec4 color1 = vec4( 1.2,0.5,0,1.);
vec3 AO = vec3(0.),AB = vec3(0.),OB = vec3(0.);
float dist = 0.;
 for (int index = 0; index <pointsNum; index++) {
    // 目的是0的时候 半径为0  这样 在 0 和 1的都会停留一会儿
    // 每个点的vu都不一样了 
    // 特解，直接求每个点到当前点的距离，得到这样一个距离场，因为现在是画圆
    //  st = v_WorldPosition;
    //  设O在平面上， A为顶点  A到平面的垂足为B 
     AO = v_WorldPosition - points[index];
     dist = dot( AO, directions[index] );
     AB = directions[index] * (-dist);
     OB = AB-AO;
     r = (time - startTimes[index]);
     c = circle2 ( dot(OB,OB), r) ;
    //  想让半径为零的时候，模糊距离为0 ，不然，初始就一个模糊的圆，不是我要的
     float f = smoothstep(0.,1.,r);
     ca +=  line(c,0.02*f , .5*f+0.001 );
}

color = mix(color, color1, ca);

      if( color.a < 0.01f){discard;}
      gl_FragColor = vec4(color);

}
`;

const uniforms = uniformsObj ||{
  u_Time: { value: 0 },
  u_CanvasSize: { value: new Vector2(vw, vh) },
  points: { value: [0,0,0] }, // 不然这里要写10个 vec2
  startTimes: { value: [0.1] }, //
  directions: { value: [1,0,1] }, //
  pointsNum: { value: 0 },
};
const pointwaveMat = new RawShaderMaterial({
  uniforms,
  glslVersion: GLSL3,
  side: DoubleSide,
  depthTest: true,
  depthwrite:false,
  vertexShader: /* glsl */ `
    // #version 300 es 
    precision highp float;
    in vec3 position;
    in vec2 uv;
    out vec3 v_WorldPosition;
    out vec2 v_Uv;
    uniform mat4 modelViewMatrix;
    uniform mat4 modelMatrix;
    uniform mat4 projectionMatrix;
    void main() {
        v_Uv = uv;
        vec4 modelPosition = modelMatrix * vec4( position, 1.0 );
        v_WorldPosition = modelPosition.xyz/modelPosition.w;
      gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }
    `,
  fragmentShader: fragment,
  transparent: true,
});

return pointwaveMat;
}